
M	EQU	Byte Ptr 0[BX]
;********************************************************
;*							*
;*	TEST ROUTINES FOR THE COMPPRO SYSTEM		*
;*	  SUPPORT 1  BOARD REAL TIME CLOCK		*
;*							*
;********************************************************
;
;	Verion 1.0	From System Support manual
;	8/1/82		Keyed in by Bill Bolton.
;
;	Version 1.10	Modified for Australian date
;	8/1/82		format by Bill Bolton.
;
;	Version 1.11	Placed version number in signon
;	11/1/82		and added version number equates
;			Bill Bolton
;
;	Version 1.12	XLT86 translation to CP/M-86
;			Bill Bolton
;
BASE	EQU	50H			;BASE PORT ADDRESS
CLKCMD	EQU	BASE+10			;CLOCK COMMAND PORT
CLKDATA	EQU	BASE+11			;CLOCK DATA PORT
WBOOT	EQU	0			;BIOS WBOOT ENTRY
BDOS	EQU	00005H			;BDOS ENTRY POINT
READ	EQU	10H			;READ BIT PATTERN
WRITE	EQU	20H			;WRITE BIT PATTERN
HOLD	EQU	40H			;HOLD BIT PATTERN
ALF	EQU	0AH			;ASCII LINE FEED
ACR	EQU	0DH			;ASCII CARRIAGE RETURN
;
VERS	EQU	1			;MAJOR VERSION NUMBER
REV	EQU	12			;MINOR REVISION NUMBER
;
	ORG	100H
;
;********************************************************
;*	THIS IS THE MAIN LOOP THAT PRINTS THE		*
;*	SIGNON MESSAGE, DECIDES WHAT COMMAND		*
;*	HAS BEEN ENTERED AND EXECUTES THAT ROUTINE	*
;********************************************************

START:
	MOV	DX,(Offset SIGNON)	;INITIAL SIGNON MESSAGE
	CALL	PMSG			;DISPLAY IT
	CALL	GETCHAR			;GET COMMAND CHARACTER
	CMP	AL,'X'			;EXIT TO CP/M ?
	JNZ	L_1	
	MOV	CL,0			;YES
	MOV	DL,0
	INT	224
L_1:
	CMP	AL,'S'			;SET TIME ?
	JZ	SETTIME			;YES
	CMP	AL,'D'			;DISPLAY TIME ?
	JNZ	L_2	
	JMP	PTIME			;YES
L_2:
	CMP	AL,'C'			;CONTIUOUS DISPLAY ?
	JNZ	L_3	
	JMP	FOREVER			;YES
L_3:
	MOV	DX,(Offset ERROR)	;CANT RECOGNIZE COMMAND
	CALL	PMSG			;SO COMPLAIN ABOUT IT
	JMPS	START			;TRY AGAIN
;
;********************************************************
;*	THIS ROUTINE SETS UP HL TO POINT TO A TABLE	*
;*	TO RECEIVE THE DIGITS TO BE WRITTEN TO THE CLOCK*
;*	DE CONTAINS THE POINTER TO THE TABLE OF ADDRESS	*
;*	VALUES THAT CORRESPOND TO THE DESIRED DIGIT.	*
;*	THE TABLE IS ORGANISED IN THE PROPER ORDER FOR	*
;*	READING AND WRITING. THE ROUTINE GETS THE	*
;*	DIGITS FROM THE CONSOLE AND PUTS THEM INTO	*
;*	MEMORY AND THEN WRITES THEM TO THE CLOCK.	*
;********************************************************
SETTIME:
	CALL	GETTIME			;GET THE DATE AND TIME DATA
	MOV	BX,(Offset DTABLE)	;HL <---- DIGIT TABLE ADDRESS
	MOV	DX,(Offset ATABLE)	;DE <---- ADDRESS TABLE
	MOV	CH,13			;NUMBER OF DIGITS TO WRITE +1
	MOV	AL,HOLD			;SET HOLD BIT
	OUT	CLKCMD,AL		;SEND COMMAND
SET1:
	DEC	CH			;DONE LAST DIGIT ?
	JNZ	HERE			;NO
	MOV	AL,0			;YES, CLEAR HOLD BIT
	OUT	CLKCMD,AL		;SEND COMMAND
	MOV	DX,(Offset TIMEIS)	;"TIME IS" MESSAGE
	CALL	PMSG
	CALL	CLKPRNT			;DISPLAY THE TIME
	JMPS	START			;NEXT COMMAND
;
HERE:
	MOV	AL,M			;A <---- DIGIT
	MOV	CL,AL			;C <---- DIGIT
	MOV	SI,DX			;A <---- COMMAND
	MOV	AL,[SI]
	CALL	WRTDGT			;WRITE THE DIGIT
	LAHF				;BUMP POINTERS
	INC	BX
	SAHF
	LAHF
	INC	DX
	SAHF
	JMPS	SET1			;NEXT DIGIT

;********************************************************
;*	THIS ROUTINE GETS THE DIGITS FROM THE CONSOLE	*
;*	AND STORES THEM INTO MEMORY AT THE ADDRESS	*
;*	POINTED TO BY HL.				*
;********************************************************

GETTIME:
	MOV	DX,(Offset ASKTIME)	;PROMPT FOR TIME INPUT
	CALL	PMSG
	MOV	BX,(Offset DTABLE)	;HL <---- ADDRESS TO PUT DIGITS
GET1:
	CALL	GETNUMB			;GET A DIGIT
	CMP	AL,ACR			;FINISHED TIME ?
	JZ	GETDATE			;YES
	AND	AL,0FH			;NO, CONVERT TO BCD FORMAT
	MOV	M,AL			;PUT DIGIT INTO MEMORY
	INC	BX			;POINT TO NEXT TABLE ADDRESS
	JMPS	GET1
;
GETDATE:
	MOV	DX,(Offset ASKDATE)	;PROMPT FOR TIME INPUT
	CALL	PMSG
GET2:
	CALL	GETNUMB			;GET A DIGIT
	CMP	AL,ACR			;FINISHED DATE ?
	JNZ	L_4	
	RET				;YES
L_4:
	AND	AL,0FH			;NO, CONVERT TO BCD
	MOV	M,AL			;PUT DIGIT INTO MEMORY
	INC	BX			;POINT TO NEXT TABLE ADDRESS
	JMPS	GET2

;********************************************************
;*	THIS ROUTINE GETS A CHARACTER FROM THE CONSOLE	*
;*	AND CHECKS THE INPUT FOR EITHER A CARRIAGE	*
;*	RETURN OR A VALID DIGIT BETWEEN 0-9 WILL NOT	*
;*	RETURN UNTIL A CR OR VALID DIGIT IS TYPED	*
;********************************************************

GETNUMB:
	CALL	GETCHAR
	CMP	AL,ACR			;CARRIAGE RETURN ?
	JNZ	L_5	
	RET				;YES
L_5:
	CMP	AL,'0'
	JB	GETNUMB
	CMP	AL,'9'+1
	JNB	GETNUMB
	RET

;********************************************************
;*	THIS ROUTINE WRITES THE DIGIT TO THE CLOCK	*
;*	AND CHECKS TO SEE IF THE HOURS OR DAYS 10	*
;*	DIGIT AND SETS THE 24 HOUR AND LEAP YEAR BITS	*
;*	ACCORDINGLY. THIS ROUTINE IS CALEED WITH DIGIT	*
;*	ADDRESS IN A AND THE DIGIT TO BE WRITTEN IN C.	*
;********************************************************

WRTDGT:
	LAHF				;SAVE THE COMMAND
	XCHG	AL,AH
	PUSH	AX
	XCHG	AL,AH
	ADD	AL,HOLD			;ADD IN THE HOLD BIT
	OUT	CLKCMD,AL		;SEND COMMAND
	CMP	AL,HOLD+5		;HOURS TEN DIGIT ?
	JNZ	WRT1			;NO
	MOV	AL,CL			;YES, GET DIGIT
	ADD	AL,08H			;SET 24 HOUR MODE
	JMPS	WRT3
;
WRT1:
	CMP	AL,8+HOLD		;DAYS 10 DIGIT ?
	JNZ	WRT2			;NO
	MOV	AL,CL			;YES, GET THE DIGIT
	AND	AL,03H			;SET NON-LEAP YEAR MODE
	JMPS	WRT3
;
WRT2:
	MOV	AL,CL			;A <---- DIGIT
WRT3:
	OUT	CLKDATA,AL		;SEND DIGIT
	POP	AX			;GET COMMAND BACK
	XCHG	AL,AH
	ADD	AL,WRITE+HOLD		;ADD THE WRITE + HOLD BITS
	OUT	CLKCMD,AL		;SEND COMMAND
	SUB	AL,WRITE		;CLEAR THE WRITE BIT
	OUT	CLKCMD,AL		;SEND COMMAND
	RET

;********************************************************
;*	THIS ROUTINE READS A DIGIT FROM THE CLOCK AND	*
;*	MASKS THE LEAP YEAR AND AND AM/PM/24 HOUR MODE	*
;*	BITS. THIS ROUTINE IS CALLED  WITH THE DIGIT	*
;*	ADDRESS IN A AND RTURNS WITH THE DIGIT VALUE	*
;*	IN A.						*
;********************************************************

RDDGT:
	ADD	AL,READ			;ADD IN THE READ BIT
	OUT	CLKCMD,AL		;SEND COMMAND
	CMP	AL,5+READ		;TENS HOURS DIGIT ?
	IN	AL,CLKDATA		;GET THE DIGIT
	JZ	L_6	
	RET				;NO, FINISHED
L_6:
	SUB	AL,08H			;YES, TURN OFF 24 HOUR BIT
	RET

;********************************************************
;*	THIS ROUTINE PRINTS THE CURRENT TIME AND DATE	*
;*	ONCE , COMPLETE WITH COLONS AND SLASHES		*
;********************************************************

CLKPRNT:
	MOV	BX,(Offset ATABLE)	;HL <---- TABLE ADDRESS
	CALL	PRINTWO			;DISPLAY THE FIRST TWO DIGITS
	MOV	AL,':'
	CALL	PCHAR			;DISPLAY THE SEPERATOR
	CALL	PRINTWO			;DISPLAY THE NEXT TWO DIGITS
	MOV	AL,':'
	CALL	PCHAR			;DISPLAY THE SEPERATOR
	CALL	PRINTWO			;DISPLAY THE NEXT TWO DIGITS
	MOV	AL,' '
	CALL	PCHAR
	MOV	AL,' '			;TWO SPACES
	CALL	PCHAR
	CALL	PRINTWO			;TWO MORE DIGITS
	MOV	AL,'/'			;DISPLAY A SLASH
	CALL	PCHAR
	CALL	PRINTWO
	MOV	AL,'/'
	CALL	PCHAR
	CALL	PRINTWO			;PRINT LAST TWO DIGITS
	RET

;********************************************************
;*	THIS ROUTINE PRINTS TWO DIGITS FROM THE CLOCK.	*
;*	IT IS CALLED WITH THE DIGIT ADDRESS OF THE	*
;*	DIGIT IN HL. EXITS WITH HL POINTING TO THE	*
;*	ADDRESS OF THE NEXT TWO DIGITS.			*
;********************************************************

PRINTWO:
	MOV	AL,M			;A <---- ADDRESS (FROM TABLE)
	CALL	RDDGT			;READ THE DIGIT
	ADD	AL,30H			;CONVERT TO ASCII
	CALL	PCHAR			;DISPLAY IT
	INC	BX			;ADJUST POINTER
	MOV	AL,M			;A <---- ADDRESS
	CALL	RDDGT
	ADD	AL,30H
	CALL	PCHAR
	LAHF
	INC	BX
	SAHF
	RET

;********************************************************
;*	THIS ROUTINE DISPLAYS THE TIME ONCE AND JUMPS	*
;*	BACK TO THE MAIN LOOP				*
;********************************************************

PTIME:
	MOV	DX,(Offset TIMEIS)
	CALL	PMSG
	CALL	CLKPRNT
	JMP	START

;********************************************************
;*	THIS ROUTINE DISPLAYS THE TIME CONTINUOUSLY	*
;*	UNTIL A CONTROL C IS TYPED. IT CONTINUALLY	*
;*	READS THE SECONDS 1 DIGIT AND WAITS FOR IT TO	*
;*	CHANGE BEFORE DISPLAYING THE TIME.		*
;********************************************************

FOREVER:
	MOV	AL,ALF			;LINE FEED
	CALL	PCHAR
FOR1:
	MOV	AL,ACR			;CR
	CALL	PCHAR
	CALL	CLKPRNT			;DISPLAY THE TIME
	MOV	AL,0			;ADDRESS OF SECONDS DIGIT
	CALL	RDDGT			;READ DIGIT
	MOV	CH,AL			;B <---- DIGIT
FOR2:
	MOV	AL,0
	CALL	RDDGT			;READ IT AGAIN
	CMP	AL,CH			;CHANGED ?
	JZ	FOR2			;NO
	JMPS	FOREVER			;YES

;********************************************************
;*	     CP/M CALLS AND UTILITY ROUTINES		*
;*							*
;*	THIS ROUTINE GETS A CHARACTER FORM THE CONSOLE	*
;*	AND CONVERTS IT TO UPPERCASE, STRIPS OF PARITY	*
;*	AND CHECKS FOR CONTROL C.			*
;********************************************************

GETCHAR:
	PUSH	BX
	MOV	CL,1			;BDOS CONSOLE IN
	INT	224
	POP	BX
	CMP	AL,'a'			;RANGE CHECK FOR UPPER CASE
	JB	SKIP
	CMP	AL,'z'+1		;DITTO
	JNB	SKIP
	AND	AL,5FH			;CONVERT TO UPPER CASE
SKIP:
	AND	AL,7FH			;STRIP PARITY BIT
	CMP	AL,03H			;CONTROL C ?
	JNZ	L_7	
	MOV	CL,0			;YES, EXIT TO CP/M
	MOV	DL,0
	INT	224
L_7:
	RET				;NO

;********************************************************
;*	THIS ROUTINE PRINTS A CHARACTER ON THE CONSOLE	*
;*	AND CHECKS TO SEE IF ANY WERE ENTERED WHILE	*
;*	PRINTING.					*
;********************************************************

PCHAR:
	PUSH	DX
	MOV	DL,AL			;E <---- CHARCATER
	MOV	CL,2			;BDOS CONSOLE OUT
	PUSH	BX
	INT	224
	MOV	CL,0BH			;BDOS CONSOLE STATUS CHECK
	INT	224
	POP	BX
	POP	DX
	OR	AL,AL			;CHARACTER READY ?
	JZ	L_8	
	CALL	GETCHAR			;YES, GET IT
L_8:
	RET				;NO

;********************************************************
;*	THIS ROUTINE DISPLAYS THE STRING POINTED TO	*
;*	BY DE UNTIL $ IS FOUND.				*
;********************************************************

PMSG:
	PUSH	BX
	MOV	CL,9			;BDOS DISPLAY STRING
	INT	224
	POP	BX
	RET
L_9	EQU	$
;
	DSEG
;
	ORG	Offset L_9

;********************************************************
;*			MESSAGES			*
;********************************************************

SIGNON	RS	0
	DB	ACR,ALF,ACR,ALF
	DB	'Time and Date Test Routines for System Support 1'
	DB	ACR,ALF
	DB	'Version ',VERS + '0','.',REV/10 + '0',REV mod 10 +'0'
	DB	ACR,ALF,ACR,ALF
	DB	'Please type one of the following Commands:'
	DB	ACR,ALF
	DB	'S - Set the Time and Date',ACR,ALF
	DB	'D - Display the Time and Date Once',ACR,ALF
	DB	'C - Continuously Display the Time and Date'
	DB	ACR,ALF
	DB	'X - Exit to Operating System'
	DB	ACR,ALF,ACR,ALF
	DB	'Command: $'
;
ERROR	RS	0
	DB	ACR,ALF
	DB	'That was not one of the above commands'
	DB	ACR,ALF
	DB	'Please try again.$'
;
ASKTIME	RS	0
	DB	ACR,ALF
	DB	'What is the time? (24 hour format - HH:MM:SS) $'
;
ASKDATE	RS	0
	DB	ACR,ALF
	DB	'What is the date? (DD/MM/YY) $'
;
TIMEIS	RS	0
	DB	ACR,ALF
	DB	'The Time and Date are: $'

;********************************************************
;*			TABLES				*
;*							*
;*	THIS TABLE CONTAINS THE 'ADDRESS' VALUES	*
;*	THAT ARE SENT IN THE COMMAND BYTE IN THE	*
;*	FOLLOWING ORDER - HOURS 10, HOURS 1, MIN 10	*
;*	MIN 1, SEC 10, SEC 1, DAYS 10, DAYS 1		*
;*	MONTHS 10, MONTHS 1, YEARS 10, YEARS 1.		*
;********************************************************

ATABLE	RS	0
	DB	5,4,3,2,1,0,8,7,0AH,9,0CH,0BH

;********************************************************
;*	THIS IS THE AREA WHICH GETS THE DIGITS AS THEY	*
;*	ARE ENTERED FROM THE CONSOLE.			*
;********************************************************

DTABLE	RS	0
	DB	0,0,0,0,0,0,0,0,0,0,0,0
;
	END
